using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;


namespace TacticalGridWars
{
    /// <summary>
    /// Handles all the Bullet objects that get fired in the game
    /// </summary>
    public class Bullets : DrawableGameComponent
    {
        #region MemberData
        private SpriteBatch spriteBatch;
        private Texture2D bulletTexture;
        private List<Bullet> BulletList;

        private int bulletCount = 0;
        private int timer = 0;
        private bool firing = false;
        private Soldier target = null;
        private bool hit;
        private Random rng = new Random((int)DateTime.Now.Ticks & 0x0000FFFF);
        private int killingShot;
        private int curBullet; 
        #endregion

        public Bullets(Game game)
            : base(game)
        {
            this.spriteBatch = new SpriteBatch(Game.GraphicsDevice);
            BulletList = new List<Bullet>();
        }

        protected override void LoadContent()
        {
            bulletTexture = this.Game.Content.Load<Texture2D>("bullet");
            base.LoadContent();
        }

        /// <summary>
        /// Fires a burst of 3 bullets from the origin to the destination and 
        /// sets the target to Dead = true if the attack is a hit
        /// </summary>
        /// <param name="xPos">Origin x</param>
        /// <param name="yPos">Origin y</param>
        /// <param name="xDest">Destination x</param>
        /// <param name="yDest">Destination y</param>
        /// <param name="target">Soldier to attack</param>
        /// <param name="hit">Attack hits</param>
        public void Fire(float xPos, float yPos, float xDest, float yDest, Soldier target, bool hit)
        {
            for (int i = 0; i < 3; i++)
            {
                int dissperssion;
                if (rng.Next(0,2) == 0)
                {
                    dissperssion = -25;
                }
                else
                {
                    dissperssion = 25;
                }
                //Start bullets at origin, then randomly dissperse them towards the target
                BulletList.Add(new Bullet(xPos, yPos, xDest + dissperssion * (float)rng.NextDouble(), 
                    yDest + dissperssion * (float)rng.NextDouble()));
            }
            this.target = target;
            this.hit = hit;
            firing = true;
            killingShot = rng.Next(1, 4);
            curBullet = 0;
        }

        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Update(GameTime gameTime)
        {
            for (int i = 0; i < bulletCount; i++)
            {
                if (BulletList[i].Finished)
                {
                    curBullet++;
                    bulletCount--;
                    BulletList.Remove(BulletList[i]);
                    if (BulletList.Count == 0)
                    {
                        firing = false;
                        bulletCount = 0;                        
                    }
                    if (curBullet == killingShot)
                    {
                        if (target != null && hit)
                        {
                            target.Dead = true;
                            target.Moves = 0;
                            target = null;
                        }
                    }
                }
                else
                {
                    BulletList[i].MoveBullet();
                }
            }

            if (firing)
            {
                timer += (int)gameTime.ElapsedGameTime.Milliseconds;
                if (timer >= 100)
                {
                    if (bulletCount < BulletList.Count)
                    {
                        bulletCount++; 
                    }
                    timer -= 100;
                } 
            }
            base.Update(gameTime);
        }

        public override void Draw(GameTime gameTime)
        {
            spriteBatch.Begin();

            for (int i = 0; i < bulletCount; i++)
            {
                spriteBatch.Draw(bulletTexture, BulletList[i].Position, Color.White);
            }

            spriteBatch.End();
            base.Draw(gameTime);
        }

        #region BulletSubClass
        /// <summary>
        /// A bullet that travels through the gamespace
        /// </summary>
        public class Bullet
        {
            #region MemberData
            private float xPos = 0;
            private float yPos = 0;
            private float xDest = 0;
            private float yDest = 0;
            private float xChange = 0;
            private float yChange = 0; 
            #endregion

            #region Properties
            public Vector2 Position
            {
                get
                {
                    return new Vector2(xPos, yPos);
                }
            }

            /// <summary>
            /// Returns true if the bullet has reached it's destination
            /// </summary>
            public bool Finished
            {
                get
                {
                    if (Math.Abs(xPos - xDest) <= 10 && Math.Abs(yPos - yDest) <= 10)
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
            } 
            #endregion

            public Bullet()
            {
                xPos = yPos = yPos = xDest = yDest = xChange = yChange = 0;
            }

            public Bullet(float xPos, float yPos, float xDest, float yDest)
            {
                this.xPos = xPos;// +22;
                this.yPos = yPos;// +22;
                this.xDest = xDest;// +22;
                this.yDest = yDest;// +22;
                this.xChange = (xDest - xPos) / 25;
                this.yChange = (yDest - yPos) / 25;
            }

            /// <summary>
            /// Moves the bullet according to it's xChange and yChange values
            /// </summary>
            public void MoveBullet()
            {
                xPos += xChange;
                yPos += yChange;
            }
        } 
        #endregion
    }
}
